home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / pluginy Firefox / 7684 / 7684.xpi / resources / fmHistory.js < prev    next >
Text File  |  2009-11-20  |  12KB  |  369 lines

  1. /**
  2.  * Copyright (c) 2008, Jose Enrique Bolanos, Jorge Villalobos
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions are met:
  7.  *
  8.  *  * Redistributions of source code must retain the above copyright notice,
  9.  *    this list of conditions and the following disclaimer.
  10.  *  * Redistributions in binary form must reproduce the above copyright notice,
  11.  *    this list of conditions and the following disclaimer in the documentation
  12.  *    and/or other materials provided with the distribution.
  13.  *  * Neither the name of Jose Enrique Bolanos, Jorge Villalobos nor the names
  14.  *    of its contributors may be used to endorse or promote products derived
  15.  *    from this software without specific prior written permission.
  16.  *
  17.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  18.  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  19.  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  20.  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
  21.  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  22.  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  23.  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  24.  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  25.  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  26.  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  27.  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28.  **/
  29.  
  30. var EXPORTED_SYMBOLS = [];
  31.  
  32. const Cc = Components.classes;
  33. const Ci = Components.interfaces;
  34. const Ce = Components.Exception;
  35.  
  36. Components.utils.import("resource://firefm/fmCommon.js");
  37. Components.utils.import("resource://firefm/fmPlayer.js");
  38. Components.utils.import("resource://firefm/fmPrivate.js");
  39. Components.utils.import("resource://firefm/fmStation.js");
  40.  
  41. // The absolute maximum to keep in the recent station history.
  42. const HISTORY_SIZE_MAX = 50;
  43.  
  44. /**
  45.  * FireFM History. Creates history entries for artists when tracks are loaded.
  46.  */
  47. FireFM.History = {
  48.  
  49.   /* Logger for this object. */
  50.   _logger : null,
  51.   /* History service */
  52.   _historyService : null,
  53.   /* Favicon service */
  54.   _faviconService : null,
  55.   /* History toggle preference object. */
  56.   _historyPref : null,
  57.   /* History size preference object. */
  58.   _historySizePref : null,
  59.   /* Station history preference object. */
  60.   _stationHistoryPref : null,
  61.   /* Store in Places history preference object. */
  62.   _storeInPlacesPref : null,
  63.   /* The station history array. */
  64.   _stationHistory : [],
  65.   /* The size of the station history. */
  66.   _historySize : 0,
  67.  
  68.   /**
  69.    * Initializes the object.
  70.    */
  71.   init : function() {
  72.     this._logger = FireFM.getLogger("FireFM.History");
  73.     this._logger.debug("init");
  74.  
  75.     this._historyService =
  76.       Cc["@mozilla.org/browser/nav-history-service;1"].
  77.         getService(Ci.nsIGlobalHistory2);
  78.     this._faviconService =
  79.       Cc["@mozilla.org/browser/favicon-service;1"].
  80.         getService(Ci.nsIFaviconService);
  81.  
  82.     this._historyPref =
  83.       FireFM.Application.prefs.get(FireFM.PREF_BRANCH + "recent.enabled");
  84.     this._historySizePref =
  85.       FireFM.Application.prefs.get(FireFM.PREF_BRANCH + "recent.historySize");
  86.     this._stationHistoryPref =
  87.       FireFM.Application.prefs.get(FireFM.PREF_BRANCH + "recent.history");
  88.     this._storeInPlacesPref =
  89.       FireFM.Application.prefs.get(FireFM.PREF_BRANCH + "storeHistory");
  90.  
  91.     this._getHistoryPreferences();
  92.  
  93.     FireFM.obsService.addObserver(
  94.       this, FireFM.Station.TOPIC_STATION_OPENING, false);
  95.     FireFM.obsService.addObserver(
  96.       this, FireFM.Player.TOPIC_TRACK_LOADED, false);
  97.   },
  98.  
  99.   /**
  100.    * Gets an array with the most recently played stations.
  101.    * @return array with the most recently played stations.
  102.    */
  103.   get stationHistory() {
  104.     this._logger.trace("[getter] stationHistory");
  105.     // XXX: this is just a hacky way of duplicating the array.
  106.     return this._stationHistory.concat([]);
  107.   },
  108.  
  109.   /**
  110.    * Clears the recent station history.
  111.    */
  112.   clearRecentHistory : function() {
  113.     this._logger.debug("clearRecentHistory");
  114.     // clear the list.
  115.     this._stationHistory.splice(0, this._stationHistory.length);
  116.     // store the preference.
  117.     this._setRecentHistoryPreference();
  118.   },
  119.  
  120.   /**
  121.    * Clears the Fire.fm entries in the browser history.
  122.    */
  123.   clearPlacesHistory : function() {
  124.     this._logger.debug("clearPlacesHistory");
  125.  
  126.     let query;
  127.     let queryOptions;
  128.     let result;
  129.     let node;
  130.     let uris;
  131.  
  132.     try {
  133.       this._historyService.QueryInterface(Ci.nsINavHistoryService);
  134.  
  135.       query = this._historyService.getNewQuery();
  136.       queryOptions = this._historyService.getNewQueryOptions();
  137.  
  138.       query.uri = FireFM.createURI("firefm://");
  139.       query.uriIsPrefix = true;
  140.  
  141.       result = this._historyService.executeQuery(query, queryOptions).root;
  142.  
  143.       this._historyService.QueryInterface(Ci.nsIBrowserHistory);
  144.  
  145.       uris = new Array();
  146.  
  147.       result.containerOpen = true;
  148.       for (var i = result.childCount - 1; 0 <= i; i--) {
  149.         uris.push(result.getChild(i).uri);
  150.       }
  151.       result.containerOpen = false;
  152.  
  153.       for (var i = uris.length - 1; 0 <= i; i--) {
  154.         this._historyService.removePage(FireFM.createURI(uris[i]));
  155.       }
  156.     } catch (e) {
  157.       this._logger.warn("Error clearing the places history: " + e);
  158.     }
  159.   },
  160.  
  161.   /**
  162.    * Records the given station information in the browser history.
  163.    * @param aStation the station to record.
  164.    * @param aImagePath the path to an icon for the station (can be null).
  165.    */
  166.   _recordStation : function(aStation, aImagePath) {
  167.     this._logger.trace("_recordStation");
  168.  
  169.     if (this._storeInPlacesPref.value && !FireFM.Private.isPrivate) {
  170.       let stationURI = null;
  171.       let title = null;
  172.       let imageURI = null;
  173.  
  174.       if (null != aImagePath) {
  175.         imageURI = FireFM.createURI(aImagePath);
  176.       }
  177.  
  178.       switch (aStation.type) {
  179.         case FireFM.Station.TYPE_ARTIST:
  180.           stationURI =
  181.             FireFM.createURI("firefm://station/artist/" + escape(aStation.id));
  182.           break;
  183.         case FireFM.Station.TYPE_RECOMMENDED:
  184.           stationURI =
  185.             FireFM.createURI(
  186.               "firefm://station/recommended/" + escape(aStation.id));
  187.           break;
  188.         case FireFM.Station.TYPE_USER:
  189.           stationURI =
  190.             FireFM.createURI("firefm://station/user/" + escape(aStation.id));
  191.           break;
  192.         case FireFM.Station.TYPE_TAG:
  193.           stationURI =
  194.             FireFM.createURI("firefm://station/tag/" + escape(aStation.id));
  195.           break;
  196.         case FireFM.Station.TYPE_NEIGHBORHOOD:
  197.           stationURI =
  198.             FireFM.createURI(
  199.               "firefm://station/neighborhood/" + escape(aStation.id));
  200.           break;
  201.         case FireFM.Station.TYPE_LOVED:
  202.           stationURI =
  203.             FireFM.createURI("firefm://station/loved/" + escape(aStation.id));
  204.           break;
  205.         default:
  206.           this._logger.error("_recordStation: Unsopported station type.");
  207.           break;
  208.       }
  209.  
  210.       title =
  211.         FireFM.overlayBundle.formatStringFromName(
  212.           "firefm.station.listenTo.label", [ aStation.title ], 1);
  213.  
  214.       if (null != stationURI) {
  215.         this._historyService.QueryInterface(Ci.nsIGlobalHistory2);
  216.  
  217.         if (!this._historyService.isVisited(stationURI)) {
  218.           this._historyService.addURI(stationURI, false, true, null);
  219.         }
  220.  
  221.         this._historyService.setPageTitle(stationURI, title);
  222.  
  223.         if (null != imageURI) {
  224.           this._faviconService.setAndLoadFaviconForPage(
  225.             stationURI, imageURI, true);
  226.         }
  227.       }
  228.     }
  229.   },
  230.  
  231.   /**
  232.    * Stores the station as the most recently loaded station.
  233.    * @param aStation the station to store.
  234.    */
  235.   _storeRecentStation : function(aStation) {
  236.     this._logger.trace("_storeRecentStation");
  237.  
  238.     if (this._historyPref.value && !FireFM.Private.isPrivate &&
  239.         (0 < this._historySize)) {
  240.       let recentCount = this._stationHistory.length;
  241.       let recent;
  242.       let newPrefValue;
  243.  
  244.       for (let i = 0; i < recentCount; i++) {
  245.         recent = this._stationHistory[i];
  246.  
  247.         // look at the current list and remove any instance of the same station.
  248.         if ((aStation.id == recent.id) && (aStation.type == recent.type)) {
  249.           this._stationHistory.splice(i, 1);
  250.           recentCount--;
  251.           break;
  252.         }
  253.       }
  254.  
  255.       // remove the last item on the list if necessary.
  256.       if (this._historySize == recentCount) {
  257.         this._stationHistory.pop();
  258.       }
  259.  
  260.       // add the station at the top of the list.
  261.       this._stationHistory.unshift(aStation);
  262.  
  263.       // set the new preference.
  264.       this._setRecentHistoryPreference();
  265.     }
  266.   },
  267.  
  268.   /**
  269.    * Gets the stored preferences for the history of recent stations. The values
  270.    * are set in this object.
  271.    */
  272.   _getHistoryPreferences : function() {
  273.     this._logger.trace("_getHistoryPreferences");
  274.  
  275.     let historyStr = this._stationHistoryPref.value;
  276.     // set the history size.
  277.     this._historySize = this._historySizePref.value;
  278.     // keep the value within reasonable constrains.
  279.     if ((null == this._historySize) || (0 > this._historySize)) {
  280.       this._historySize = 0;
  281.     } else if (HISTORY_SIZE_MAX < this._historySize) {
  282.       this._historySize = HISTORY_SIZE_MAX;
  283.     }
  284.  
  285.     // set the station history.
  286.     try {
  287.       let arr = JSON.parse(historyStr);
  288.       let arrItem;
  289.  
  290.       for (let i = 0; ((i < arr.length) && (i < this._historySize)); i++) {
  291.         arrItem = arr[i];
  292.         this._stationHistory.push(
  293.           new FireFM.StationInfo(arrItem.id, arrItem.type));
  294.       }
  295.     } catch (e) {
  296.       this._logger.error(e);
  297.       this._logger.warn(
  298.         "_getHistoryPreferences. Invalid value for history preference: " +
  299.         historyStr);
  300.       this._stationHistory = [];
  301.     }
  302.   },
  303.  
  304.   /**
  305.    * Sets the recent history preference with the current state of the recent
  306.    * stations list.
  307.    */
  308.   _setRecentHistoryPreference : function() {
  309.     this._logger.trace("_setRecentHistoryPreference");
  310.  
  311.     let recentCount = this._stationHistory.length;
  312.     let newPrefValue = "[ ";
  313.  
  314.     // generate the new value.
  315.     for (let i = 0; i < recentCount; i++) {
  316.       if (0 != i) {
  317.         newPrefValue += ", "
  318.       }
  319.  
  320.       newPrefValue += this._stationHistory[i].toJSON();
  321.     }
  322.  
  323.     newPrefValue += " ]";
  324.  
  325.     this._logger.debug(
  326.       "_setRecentHistoryPreference. Preference value: " + newPrefValue);
  327.     // store the new value in the preference.
  328.     this._stationHistoryPref.value = newPrefValue;
  329.   },
  330.  
  331.   /**
  332.    * Observes topic notifications.
  333.    * @param aSubject The object that experienced the change.
  334.    * @param aTopic The topic being observed.
  335.    * @param aData The data relating to the change.
  336.    */
  337.   observe : function(aSubject, aTopic, aData) {
  338.     this._logger.debug("observe");
  339.  
  340.     switch (aTopic) {
  341.       case FireFM.Station.TOPIC_STATION_OPENING:
  342.         if (null != aSubject) {
  343.           let station = aSubject.wrappedJSObject;
  344.           // save station to the recent station history.
  345.           this._storeRecentStation(station);
  346.           // save station to the user's Places history.
  347.           this._recordStation(station, null);
  348.         }
  349.  
  350.         break;
  351.  
  352.       case FireFM.Player.TOPIC_TRACK_LOADED:
  353.         let track = aSubject.wrappedJSObject;
  354.         let station =
  355.           new FireFM.StationInfo(track.artist, FireFM.Station.TYPE_ARTIST);
  356.  
  357.         this._recordStation(station, track.imagePath);
  358.         break;
  359.     }
  360.   }
  361. };
  362.  
  363. /**
  364.  * FireFM.History constructor.
  365.  */
  366. (function() {
  367.   this.init();
  368. }).apply(FireFM.History);
  369.